package wordParseAnalyzer;

import java.io.*;
import java.util.Arrays;
import java.util.HashSet;
import java.util.Set;



public class WordParseAnalyzer {

    //关键字表
    public static Set<String> KeyWordTable = new HashSet<>();
    //界符表
    public static Set<Character> DelimiterTable = new HashSet<>();
    //标识符表
    public static Set<String> IdentifierTable = new HashSet<>();
    //常数表
    public static Set<String> DigitTable = new HashSet<>();
    //关系运算符表
    public static Set<String> OperatorTable = new HashSet<>();

    static int KeyWordNum = 0;

    static int RelationalOperatorNum = 0;

    static {
        System.out.println("a");
        initKeyWord();
        initDelimiter();
    }

    private static void initDelimiter() {
        //界符表
        Character[] JieFu = {
                ';', '(', ')', '^', ',', '#', '%', '[', ']', '{', '}', '.', '@'
        };

        DelimiterTable.addAll(Arrays.asList(JieFu));
    }

    public static void initKeyWord() {
        KeyWordTable.clear();
        //关键字符
        String[] keyWords = {
                "int", "assert", "boolean", "break", "byte", "case", "catch", "char", "class", "continue", "false",
                "default", "do", "double", "else", "enum", "extends", "final", "finally", "float", "for", "true",
                "if", "implements", "import", "abstract", "interface", "instanceof", "long", "native", "new", "System",
                "package", "private", "protected", "public", "while", "return", "short", "volatile", "String", "main",
                "static", "super", "switch", "synchronized", "this", "throw", "throws", "transient", "try", "void"
        };
        KeyWordTable.addAll(Arrays.asList(keyWords));
    }


    //判断是否是：字母
    public static boolean IsLetter(char x) {
        return (x >= 'a' && x <= 'z') || (x >= 'A' && x <= 'Z');
    }

    //判断是否是：数字
    public static boolean IsDigit(char x) {
        return x >= '0' && x <= '9';
    }

    //判断是否是：界符
    public static boolean IsDelimiter(char x) {
        return DelimiterTable.contains(x);
    }

    //判断是否是：关键字
    public static boolean isKeyWord(String str) {
        for (String keyword : KeyWordTable
        ) {
            if (str.equals(keyword)) {
                return true;
            }
        }
        return false;
    }

    //判断是否是 算数运算符：加减乘
    public static boolean IsArithmeticOperator(char x) {
        return x == '+' || x == '-' || x == '*';
    }

    //判断是否是 关系运算符：等于（赋值），大于小于（大于等于，小于等于，大于小于）
    public static boolean IsRelationalOperator(char x) {
        return x == '=' || x == '<' || x == '>';
    }


    //判断是否是注释，如果是则提取注释内容
    public static int annotationHandler(String content, BufferedWriter annotationWriter, BufferedWriter errorWriter, BufferedReader bReader, int LineNum) throws IOException {
        int index = content.indexOf('/');
        if (index == content.length() - 1) {
            errorWriter.write("有错误在第 " + LineNum + " 行 " + "（注释书写错误）" + "\r\n");
        } else {
            if (index != -1 && (content.charAt(index + 1) != '*' || content.charAt(index + 1) != '/')) {
                errorWriter.write("有错误在第 " + LineNum + " 行 " + "（注释书写错误）" + "\r\n");
            }
            boolean printSign = true;
            if (index != -1) {
                index++;
                char c = content.charAt(index);
                switch (c) {
                    case '*':
                        if (printSign) {
                            annotationWriter.write("捕获到注释" + "\r\n");
                            annotationWriter.write("/*" + "\r\n");
                            printSign = false;
                        }
                        while ((content = bReader.readLine()) != null) {
                            LineNum++;
                            if (content.contains("*") && content.contains("/")) {
                                if ((content.indexOf('/') - content.indexOf('*')) == 1 && (content.indexOf('/') != content.length() - 1)) {
                                    errorWriter.write("有错误在第 " + LineNum + " 行 第 " + "（注释书写错误）" + "\r\n");
                                }
                                annotationWriter.write("*/" + "\r\n");
                                break;
                            } else {
                                annotationWriter.write(content + "\r\n");
                            }
                        }
                        break;
                    case '/':
                        annotationWriter.write("捕获到注释" + "\r\n");
                        annotationWriter.write(content + "\r\n");
                        break;
                }
            }
        }
        return LineNum;
    }

    //特殊import导入其他的类
    public static boolean IsImport(String str) {
        return str.equals("import");
    }

    //用来比较的作为工具的方法
    public static boolean compare(String s1, String s2) {
        byte[] b1 = s1.getBytes();
        byte[] b2 = s2.getBytes();
        Arrays.sort(b1);
        Arrays.sort(b2);
        s1 = new String(b1);
        s2 = new String(b2);
        return s1.equals(s2);
    }

    public static void read_write_File() throws IOException {

        FileReader reader = new FileReader("totalInput.txt");
        BufferedReader bReader = new BufferedReader(reader);

        FileWriter writer = new FileWriter("totalOutput.txt");
        BufferedWriter totalWriter = new BufferedWriter(writer);
        FileWriter writer1 = new FileWriter("KeyWordTableOut.txt");
        BufferedWriter keyWordWriter = new BufferedWriter(writer1);
        FileWriter writer2 = new FileWriter("IdentifierTableOut.txt");
        BufferedWriter identifierWriter = new BufferedWriter(writer2);
        FileWriter writer3 = new FileWriter("ArithmeticOperatorOut.txt");
        BufferedWriter arithmeticWriter = new BufferedWriter(writer3);
        FileWriter writer4 = new FileWriter("DigitOut.txt");
        BufferedWriter digitWriter = new BufferedWriter(writer4);
        FileWriter writer5 = new FileWriter("DelimiterOut.txt");
        BufferedWriter delimiterWriter = new BufferedWriter(writer5);
        FileWriter writer6 = new FileWriter("OperatorOut.txt");
        BufferedWriter operatorWriter = new BufferedWriter(writer6);
        FileWriter writer7 = new FileWriter("IntroductionClassOut.txt");
        BufferedWriter introductionClassWriter = new BufferedWriter(writer7);
        FileWriter writer8 = new FileWriter("ErrorOut.txt");
        BufferedWriter errorWriter = new BufferedWriter(writer8);
        FileWriter writer9 = new FileWriter("AnnotationOut.txt");
        BufferedWriter annotationWriter = new BufferedWriter(writer9);


        String content = "";
        boolean IsFirstWord;
        int LineNum = 1;
        boolean importSign = true;

        while ((content = bReader.readLine()) != null) {

            int count = 0;

            IsFirstWord = true;

            LineNum = annotationHandler(content, annotationWriter, errorWriter, bReader, LineNum);


            while (count < content.length()) {

                if (content.charAt(count) == ' ') {
                    count++;
                } else if (IsLetter(content.charAt(count)) || content.charAt(count) == '_') {
                    String str = "";
                    str += content.charAt(count++);
                    while (count < content.length() && (IsLetter(content.charAt(count)) || IsDigit(content.charAt(count)) || content.charAt(count) == '_')) {
                        str += content.charAt(count++);
                    }
                    if (IsFirstWord) {
                        if (isKeyWord(str)) {
                            while (content.charAt(count) == ' ') {
                                count++;
                            }
                            String tempStr = "";
                            tempStr += content.charAt(count);
                            while (content.charAt(count) != ' ') {
                                count++;
                                if (count < content.length()) {
                                    tempStr += content.charAt(count);
                                } else {
                                    break;
                                }
                            }
                            if (isKeyWord(tempStr)) {
                                errorWriter.write("有错误在第 " + LineNum + " 行 第 " + (count - tempStr.length() + " 列"));
                            }
                        }
                    }
                    IsFirstWord = false;
                    if (IsImport(str)) {
                        totalWriter.write("(" + "导入声明类： " + content + ")" + "\r\n");
                        introductionClassWriter.write("(" + "导入声明类： " + content + ")" + "\r\n");
                        if (importSign) {
                            keyWordWriter.write("(" + "关键字：" + str + ")" + "\r\n");
                            KeyWordTable.remove(str);
                            importSign = false;
                        }
                        break;
                    }
                    if (KeyWordTable.contains(str)) {
                        totalWriter.write("(" + "关键字：" + str + ")" + "\r\n");
                        keyWordWriter.write("(" + "关键字：" + str + ")" + "\r\n");
                        KeyWordNum++;
                        continue;
                    }
                    if (!KeyWordTable.contains(str)) {
                        totalWriter.write("(" + "标识符" + "," + str + ")" + "\r\n");
                        if (!IdentifierTable.contains(str)) {
                            IdentifierTable.add(str);
                            identifierWriter.write("(" + "标识符" + "," + str + ")" + "\r\n");
                        }
                    }
                } else if (IsArithmeticOperator(content.charAt(count))) {
                    String str = "";
                    str += content.charAt(count++);
                    totalWriter.write("(" + "算术运算符" + "," + str + ")" + "\r\n");
                    if (!OperatorTable.contains(str)) {
                        OperatorTable.add(str);
                        arithmeticWriter.write("(" + "算术运算符: " + str + ")" + "\r\n");
                    }
                } else if (IsDigit(content.charAt(count))) {
                    String str = "";
                    str += content.charAt(count++);
                    while (count < content.length() && IsDigit(content.charAt(count))) {
                        str += content.charAt(count++);
                    }
                    DigitTable.add(str);
                    totalWriter.write("(" + "数字" + "," + str + ")" + "\r\n");
                    digitWriter.write("(" + "数字" + "," + str + ")" + "\r\n");
                } else if (IsDelimiter(content.charAt(count))) {
                    String str = "";
                    str += content.charAt(count);
                    totalWriter.write("(" + "界符" + "," + str + ")" + "\r\n");
                    delimiterWriter.write("(" + "界符" + "," + str + ")" + "\r\n");
                    count++;
                } else if (IsRelationalOperator(content.charAt(count))) {
                    String str = "";
                    char c = content.charAt(count);
                    switch (c) {
                        case '>':
                        case '<':
                        case '=':
                            str += c + "";
                            c = content.charAt(count + 1);
                            if (c == '=') {
                                str += c + "";
                            }
                            count++;
                            RelationalOperatorNum++;
                            break;
                    }
                    operatorWriter.write("(" + "关系运算符: " + str + " )" + "\r\n");
                    break;
                } else {
                    String str = "";
                    str += content.charAt(count);
                    count++;
                    totalWriter.write("(" + "未知字符" + "," + str + ")" + "\r\n");
                }
            }
            LineNum++;
        }

        keyWordWriter.write("关键字出现了 " + KeyWordNum + " 个");
        identifierWriter.write("标识符共有 " + IdentifierTable.size() + " 个");
        arithmeticWriter.write("算术运算符共有 " + OperatorTable.size() + " 个");
        digitWriter.write("常数共有 " + DigitTable.size() + " 个");
        delimiterWriter.write("界符出现了 " + DelimiterTable.size() + " 个");
        operatorWriter.write("关系运算符共有 " + RelationalOperatorNum + " 个");

        reader.close();
        bReader.close();
        totalWriter.close();
        writer.close();
        keyWordWriter.close();
        writer1.close();
        identifierWriter.close();
        writer2.close();
        arithmeticWriter.close();
        writer3.close();
        digitWriter.close();
        writer4.close();
        delimiterWriter.close();
        writer5.close();
        operatorWriter.close();
        writer6.close();
        introductionClassWriter.close();
        writer7.close();
        errorWriter.close();
        writer8.close();
        annotationWriter.close();
        writer9.close();
        System.out.println("已完成 更多信息查看对应文件");
    }

    public static void main(String[] args) throws IOException {
        read_write_File();
    }
}